/**
 * Copyright (c) 2016-2019 人人开源 All rights reserved.
 *
 * https://www.renren.io
 *
 * 版权所有，侵权必究！
 */

package io.renren.modules.sys.controller;


import com.google.code.kaptcha.Constants;
import com.google.code.kaptcha.Producer;
import io.renren.common.utils.R;
import io.renren.modules.sys.entity.SysUserEntity;
import io.renren.modules.sys.service.SysUserService;
import io.renren.modules.sys.shiro.ShiroUtils;
import org.apache.http.HttpEntity;
import org.apache.http.HttpStatus;
import org.apache.http.NameValuePair;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;
import org.apache.shiro.authc.*;
import org.apache.shiro.subject.Subject;
import org.json.JSONObject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.imageio.ImageIO;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 * 登录相关
 *
 * @author Mark sunlightcs@gmail.com
 */
@Controller
public class SysLoginController {
	@Autowired
	private Producer producer;
	@Autowired
	private SysUserService sysUserService;

	@Value("${oauth.grantType}")
	String grantType;
	@Value("${oauth.clientId}")
	String clientId;
	@Value("${oauth.clientSecret}")
	String clientSecret;
	@Value("${oauth.url2}")
	String url;
	@Value("${oauth.redirectUri}")
	String redirectUri;
	@Value("${oauth.url3}")
	String url3;
	@RequestMapping("captcha.jpg")
	public void captcha(HttpServletResponse response)throws IOException {
        response.setHeader("Cache-Control", "no-store, no-cache");
        response.setContentType("image/jpeg");

        //生成文字验证码
        String text = producer.createText();
        //生成图片验证码
        BufferedImage image = producer.createImage(text);
        //保存到shiro session
        ShiroUtils.setSessionAttribute(Constants.KAPTCHA_SESSION_KEY, text);
        
        ServletOutputStream out = response.getOutputStream();
        ImageIO.write(image, "jpg", out);
	}
	/**
	 * 登录
	 */
	@ResponseBody
	@RequestMapping(value = "/sys/logins", method = RequestMethod.POST)
	public R login(String username, String password) {

		try{
			Subject subject = ShiroUtils.getSubject();
			UsernamePasswordToken token = new UsernamePasswordToken(username, password);
			subject.login(token);
		}catch (UnknownAccountException e) {
			return R.error(e.getMessage());
		}catch (IncorrectCredentialsException e) {
			return R.error("账号或密码不正确");
		}catch (LockedAccountException e) {
			return R.error("账号已被锁定,请联系管理员");
		}catch (AuthenticationException e) {
			return R.error("账户验证失败");
		}

		return R.ok();
	}
	/**
	 * 登录
	 */
	@ResponseBody
	@RequestMapping(value = "/sys/login", method = RequestMethod.GET)
	public void login(@RequestParam Map<String, Object> map, HttpServletResponse response, HttpServletRequest request) throws Exception {

		String code = String.valueOf(map.get("code"));
		//获取token
		String tokens = getToken(code);
		//获取教师编号
		String id = getUserId(tokens);
		//获取该教师编号是否存在
		SysUserEntity entity = sysUserService.getUserByJxbh(id);
		if (entity == null) {
			entity = new SysUserEntity();
			entity.setUsername("demo");
		}

		try {
			Subject subject = ShiroUtils.getSubject();
			UsernamePasswordToken token = new UsernamePasswordToken(entity.getUsername(), "cdgz2020!");
			subject.login(token);
		}catch (UnknownAccountException e) {
//			return R.error(e.getMessage());
		}catch (IncorrectCredentialsException e) {
//			return R.error("账号或密码不正确");
		}catch (LockedAccountException e) {
//			return R.error("账号已被锁定,请联系管理员");
		}catch (AuthenticationException e) {
//			return R.error("账户验证失败");
		}

		response.sendRedirect(request.getContextPath()+"/index.html");
	}
	
	/**
	 * 退出
	 */
	@RequestMapping(value = "logout", method = RequestMethod.GET)
	public String logout() {
		ShiroUtils.logout();
		return "redirect:login.html";
	}

	public String getToken(String code) throws Exception {
		// 获取默认的请求客户端
		CloseableHttpClient client = HttpClients.createDefault();
		// 通过HttpPost来发送post请求
		HttpPost httpPost = new HttpPost(url);
		/*
		 * post带参数开始
		 */
		// 第三步：构造list集合，往里面丢数据
		List<NameValuePair> list = new ArrayList<NameValuePair>();
		BasicNameValuePair basicNameValuePair = new BasicNameValuePair("grant_type", grantType);
		BasicNameValuePair basicNameValuePair2 = new BasicNameValuePair("client_id", clientId);
		BasicNameValuePair basicNameValuePair3 = new BasicNameValuePair("client_secret", clientSecret);
		BasicNameValuePair basicNameValuePair4 = new BasicNameValuePair("code", code);
		BasicNameValuePair basicNameValuePair5 = new BasicNameValuePair("redirect_uri", redirectUri);
		list.add(basicNameValuePair);
		list.add(basicNameValuePair2);
		list.add(basicNameValuePair3);
		list.add(basicNameValuePair4);
		list.add(basicNameValuePair5);
		// 第二步：我们发现Entity是一个接口，所以只能找实现类，发现实现类又需要一个集合，集合的泛型是NameValuePair类型
		UrlEncodedFormEntity formEntity = new UrlEncodedFormEntity(list);
		// 第一步：通过setEntity 将我们的entity对象传递过去
		httpPost.setEntity(formEntity);
		/*
		 * post带参数结束
		 */
		// HttpEntity
		// 是一个中间的桥梁，在httpClient里面，是连接我们的请求与响应的一个中间桥梁，所有的请求参数都是通过HttpEntity携带过去的
		// 通过client来执行请求，获取一个响应结果
		CloseableHttpResponse response = client.execute(httpPost);
		HttpEntity entity = response.getEntity();
		String str = EntityUtils.toString(entity, "UTF-8");
		int statusCode = response.getStatusLine().getStatusCode();
		JSONObject jo = new JSONObject(str);

		if (statusCode != HttpStatus.SC_OK) {
			//TODO:状态码非200代表没有正常返回,此处处理你的业务
			String error = String.valueOf(jo.get("error_description"));
			System.out.println("登录错误" + error);
			return null;
		}
		System.out.println(jo);
		// 关闭
		response.close();
		String token = String.valueOf(jo.get("access_token"));
		return token;
	}

	public String getUserId(String token) throws Exception {
		// 获取默认的请求客户端
		CloseableHttpClient client = HttpClients.createDefault();
		// 通过HttpPost来发送post请求
		HttpPost httpPost = new HttpPost(url3);
		/*
		 * post带参数开始
		 */
		// 第三步：构造list集合，往里面丢数据
		List<NameValuePair> list = new ArrayList<NameValuePair>();
		BasicNameValuePair basicNameValuePair = new BasicNameValuePair("access_token", token);
		list.add(basicNameValuePair);
		// 第二步：我们发现Entity是一个接口，所以只能找实现类，发现实现类又需要一个集合，集合的泛型是NameValuePair类型
		UrlEncodedFormEntity formEntity = new UrlEncodedFormEntity(list);
		// 第一步：通过setEntity 将我们的entity对象传递过去
		httpPost.setEntity(formEntity);

		// HttpEntity
		// 是一个中间的桥梁，在httpClient里面，是连接我们的请求与响应的一个中间桥梁，所有的请求参数都是通过HttpEntity携带过去的
		// 通过client来执行请求，获取一个响应结果
		CloseableHttpResponse response = client.execute(httpPost);
		HttpEntity entity = response.getEntity();
		String str = EntityUtils.toString(entity, "UTF-8");
		int statusCode = response.getStatusLine().getStatusCode();
		JSONObject jo = new JSONObject(str);

		if (statusCode != HttpStatus.SC_OK) {
			//TODO:状态码非200代表没有正常返回,此处处理你的业务
			String error = String.valueOf(jo.get("error"));
			System.out.println("登录错误" + error);
			return null;
		}
		System.out.println(jo);
		// 关闭
		response.close();
		String id = String.valueOf(jo.get("id"));
		return id;
	}
	
}
